import * as forge from 'node-forge';

export interface CertificateConfig {
    commonName: string;
    organization: string;
    organizationalUnit: string;
    country: string;
    state: string;
    city: string;
    keyAlgorithm: string;
    keySize: string;
    validityDays: string;
    signatureAlgorithm: string;
    sanDomains: string;
    sanIPs: string;
}

export interface GeneratedFile {
    name: string;
    content: string;
    size: number;
}

export class CertificateGenerator {
    private config: CertificateConfig;

    constructor(config: CertificateConfig) {
        this.config = config;
    }

    async generateCertificate(): Promise<GeneratedFile[]> {
        try {
            // 生成私钥对象和PEM字符串
            const { privateKeyObj, privateKeyPem } = await this.generatePrivateKey();
            
            // 验证私钥生成
            if (!privateKeyObj || !privateKeyPem) {
                throw new Error('私钥生成失败');
            }
            
            // 生成证书签名请求 (CSR)
            const csr = await this.generateCSR(privateKeyObj);
            
            // 生成自签名证书
            const certificate = await this.generateSelfSignedCertificate(privateKeyObj);
            
            // 生成CA证书
            const caCertificate = await this.generateCACertificate();

            // 验证所有文件都成功生成
            if (!csr || !certificate || !caCertificate) {
                throw new Error('证书文件生成失败');
            }

            return [
                {
                    name: 'server.key',
                    content: privateKeyPem,
                    size: privateKeyPem.length
                },
                {
                    name: 'server.csr',
                    content: csr,
                    size: csr.length
                },
                {
                    name: 'server.crt',
                    content: certificate,
                    size: certificate.length
                },
                {
                    name: 'ca.crt',
                    content: caCertificate,
                    size: caCertificate.length
                }
            ];
        } catch (error) {
            console.error('证书生成详细错误:', error);
            throw new Error(`证书生成失败: ${error instanceof Error ? error.message : '未知错误'}`);
        }
    }

    private async generatePrivateKey(): Promise<{ privateKeyObj: any; privateKeyPem: string }> {
        // 生成RSA私钥
        const keySize = parseInt(this.config.keySize);
        const algorithm = this.config.keyAlgorithm;
        
        let privateKey: any;
        
        if (algorithm === 'RSA') {
            // 生成RSA密钥对
            const keys = forge.pki.rsa.generateKeyPair(keySize);
            privateKey = keys.privateKey;
        } else if (algorithm === 'ECDSA') {
            // 生成ECDSA密钥对
            const keys = forge.pki.ed25519.generateKeyPair();
            privateKey = keys.privateKey;
        } else {
            throw new Error(`不支持的密钥算法: ${algorithm}`);
        }
        
        // 生成PEM格式的私钥（始终生成未加密的私钥）
        const privateKeyPem = forge.pki.privateKeyToPem(privateKey);
        
        return { privateKeyObj: privateKey, privateKeyPem };
    }

    private async generateCSR(privateKeyObj: any): Promise<string> {
        // 创建CSR
        const csr = forge.pki.createCertificationRequest();
        
        // 设置公钥（从私钥中提取）
        csr.publicKey = privateKeyObj as any;
        
        // 设置主题 - 使用简化的主题
        const subject = [
            {
                shortName: 'CN',
                value: this.config.commonName || 'localhost'
            },
            {
                shortName: 'O',
                value: this.config.organization || 'Test Organization'
            },
            {
                shortName: 'C',
                value: this.config.country || 'CN'
            }
        ];
        
        csr.setSubject(subject);
        
        // 使用私钥签名CSR
        const md = this.config.signatureAlgorithm === 'sha256' ? forge.md.sha256.create() : 
                  this.config.signatureAlgorithm === 'sha384' ? forge.md.sha384.create() : forge.md.sha512.create();
        csr.sign(privateKeyObj, md);
        
        return forge.pki.certificationRequestToPem(csr);
    }

    private async generateSelfSignedCertificate(privateKeyObj: any): Promise<string> {
        // 创建证书
        const cert = forge.pki.createCertificate();
        
        // 设置公钥
        cert.publicKey = privateKeyObj as any;
        
        // 设置序列号
        cert.serialNumber = '01';
        
        // 设置有效期
        const now = new Date();
        const validityDays = parseInt(this.config.validityDays);
        cert.validity.notBefore = now;
        cert.validity.notAfter = new Date(now.getTime() + validityDays * 24 * 60 * 60 * 1000);
        
        // 设置主题和颁发者 - 使用简化的主题
        const subject = [
            {
                shortName: 'CN',
                value: this.config.commonName || 'localhost'
            },
            {
                shortName: 'O',
                value: this.config.organization || 'Test Organization'
            },
            {
                shortName: 'C',
                value: this.config.country || 'CN'
            }
        ];
        
        cert.setSubject(subject);
        cert.setIssuer(subject); // 自签名证书
        
        // 设置基本扩展
        cert.setExtensions([
            {
                name: 'basicConstraints',
                cA: false
            },
            {
                name: 'keyUsage',
                keyCertSign: false,
                digitalSignature: true,
                keyEncipherment: true
            },
            {
                name: 'extKeyUsage',
                serverAuth: true,
                clientAuth: true
            }
        ]);
        
        // 使用私钥签名证书
        const md = this.config.signatureAlgorithm === 'sha256' ? forge.md.sha256.create() : 
                  this.config.signatureAlgorithm === 'sha384' ? forge.md.sha384.create() : forge.md.sha512.create();
        cert.sign(privateKeyObj, md);
        
        return forge.pki.certificateToPem(cert);
    }

    private async generateCACertificate(): Promise<string> {
        // 生成CA私钥
        const caKeys = forge.pki.rsa.generateKeyPair(2048);
        
        // 创建CA证书
        const caCert = forge.pki.createCertificate();
        
        // 设置公钥
        caCert.publicKey = caKeys.publicKey;
        
        // 设置序列号
        caCert.serialNumber = '01';
        
        // 设置有效期（CA证书通常有效期更长）
        const now = new Date();
        caCert.validity.notBefore = now;
        caCert.validity.notAfter = new Date(now.getTime() + 3650 * 24 * 60 * 60 * 1000); // 10年
        
        // 设置主题和颁发者
        const subject = [
            {
                shortName: 'CN',
                value: `CA-${this.config.organization || 'Test Organization'}`
            },
            {
                shortName: 'O',
                value: this.config.organization || 'Test Organization'
            },
            {
                shortName: 'C',
                value: this.config.country || 'CN'
            }
        ];
        caCert.setSubject(subject);
        caCert.setIssuer(subject); // 自签名CA
        
        // 设置CA扩展
        caCert.setExtensions([
            {
                name: 'basicConstraints',
                cA: true,
                pathLenConstraint: 1
            },
            {
                name: 'keyUsage',
                keyCertSign: true,
                cRLSign: true
            }
        ]);
        
        // 使用CA私钥签名
        const md = forge.md.sha256.create();
        caCert.sign(caKeys.privateKey, md);
        
        return forge.pki.certificateToPem(caCert);
    }

    private buildSubject(): string {
        const parts = [];
        
        if (this.config.commonName) {
            parts.push(`CN=${this.config.commonName}`);
        }
        if (this.config.organization) {
            parts.push(`O=${this.config.organization}`);
        }
        if (this.config.organizationalUnit) {
            parts.push(`OU=${this.config.organizationalUnit}`);
        }
        if (this.config.country) {
            parts.push(`C=${this.config.country}`);
        }
        if (this.config.state) {
            parts.push(`ST=${this.config.state}`);
        }
        if (this.config.city) {
            parts.push(`L=${this.config.city}`);
        }
        
        return parts.join(', ');
    }

    private buildExtensions(): any[] {
        const extensions = [];
        
        // 基本约束
        extensions.push({
            extnID: '2.5.29.19', // Basic Constraints
            critical: true,
            extnValue: {
                cA: false,
                pathLenConstraint: undefined
            }
        });
        
        // 密钥用途
        extensions.push({
            extnID: '2.5.29.15', // Key Usage
            critical: true,
            extnValue: {
                digitalSignature: true,
                keyEncipherment: true,
                dataEncipherment: false,
                keyAgreement: false,
                keyCertSign: false,
                cRLSign: false,
                encipherOnly: false,
                decipherOnly: false
            }
        });
        
        // 扩展密钥用途
        extensions.push({
            extnID: '2.5.29.37', // Extended Key Usage
            critical: false,
            extnValue: {
                '1.3.6.1.5.5.7.3.1': true, // TLS Web Server Authentication
                '1.3.6.1.5.5.7.3.2': true  // TLS Web Client Authentication
            }
        });
        
        // 主题备用名称
        if (this.config.sanDomains || this.config.sanIPs) {
            const sanValues: Array<{ type: string; value: string }> = [];
            
            if (this.config.sanDomains) {
                const domains = this.config.sanDomains.split(',').map(d => d.trim());
                domains.forEach(domain => {
                    if (domain) {
                        sanValues.push({ type: 'dNSName', value: domain });
                    }
                });
            }
            
            if (this.config.sanIPs) {
                const ips = this.config.sanIPs.split(',').map(ip => ip.trim());
                ips.forEach(ip => {
                    if (ip) {
                        sanValues.push({ type: 'iPAddress', value: ip });
                    }
                });
            }
            
            if (sanValues.length > 0) {
                extensions.push({
                    extnID: '2.5.29.17', // Subject Alternative Name
                    critical: false,
                    extnValue: sanValues
                });
            }
        }
        
        return extensions;
    }

    // 解析主题字符串为forge格式
    private parseSubject(subject: string): any[] {
        const result: any[] = [];
        const parts = subject.split(', ');
        
        parts.forEach(part => {
            const [type, value] = part.split('=');
            if (type && value) {
                result.push({
                    shortName: type,
                    value: value
                });
            }
        });
        
        return result;
    }

    // 设置证书扩展
    private setCertificateExtensions(cert: any): void {
        // 基本约束
        cert.setExtensions([
            {
                name: 'basicConstraints',
                cA: false
            },
            {
                name: 'keyUsage',
                keyCertSign: false,
                digitalSignature: true,
                keyEncipherment: true
            },
            {
                name: 'extKeyUsage',
                serverAuth: true,
                clientAuth: true
            }
        ]);
    }


} 